<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ETNOR-OPS 一体化自动部署方案</title>
    <!-- 引入外部依赖 -->
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

    <style>
        :root {
            --primary-color: #4299e1;
            --secondary-color: #2d3748;
            --success-color: #48bb78;
            --error-color: #f56565;
            --warning-color: #ed8936;
        }

        .gradient-bg {
            background: linear-gradient(120deg, #1a365d 0%, #2d3748 100%);
        }

        .glass-effect {
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }

        .input-style {
            background: rgba(255, 255, 255, 0.05);
            border: 1px solid rgba(255, 255, 255, 0.1);
            transition: all 0.3s ease;
            color: #fff;
        }

        .input-style:focus {
            background: rgba(255, 255, 255, 0.1);
            border-color: var(--primary-color);
            box-shadow: 0 0 0 2px rgba(66, 153, 225, 0.2);
            outline: none;
        }

        .tab-active {
            border-bottom: 2px solid var(--primary-color);
            color: var(--primary-color);
        }

        .progress-bar {
            position: relative;
            overflow: hidden;
        }

        .progress-fill {
            transition: width 0.3s ease;
        }

        .progress-bar:hover {
            opacity: 0.8;
        }

        .tooltip {
            position: relative;
        }

        .tooltip:hover::after {
            content: attr(data-tooltip);
            position: absolute;
            bottom: 100%;
            left: 50%;
            transform: translateX(-50%);
            padding: 4px 8px;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            border-radius: 4px;
            font-size: 12px;
            white-space: nowrap;
            z-index: 10;
        }

        .animate-pulse {
            animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
        }

        @keyframes pulse {
            0%, 100% {
                opacity: 1;
            }
            50% {
                opacity: .5;
            }
        }

        /* 自定义滚动条 */
        ::-webkit-scrollbar {
            width: 8px;
            height: 8px;
        }

        ::-webkit-scrollbar-track {
            background: rgba(255, 255, 255, 0.1);
            border-radius: 4px;
        }

        ::-webkit-scrollbar-thumb {
            background: rgba(255, 255, 255, 0.2);
            border-radius: 4px;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: rgba(255, 255, 255, 0.3);
        }

        /* 加载动画 */
        .loading-spinner {
            border: 3px solid rgba(255, 255, 255, 0.1);
            border-radius: 50%;
            border-top: 3px solid var(--primary-color);
            width: 20px;
            height: 20px;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>
<body class="gradient-bg min-h-screen text-gray-100">
    <!-- 导航栏 -->
    <nav class="glass-effect fixed top-0 left-0 right-0 z-50">
        <div class="container mx-auto px-4 py-3">
            <div class="flex justify-between items-center">
                <div class="flex items-center space-x-4">
                    <i class="fas fa-server text-2xl text-blue-400"></i>
                    <h1 class="text-xl font-bold">ETNOR-OPS</h1>
                </div>
                <div class="flex items-center space-x-4">
                    <select id="language" class="input-style rounded-lg px-3 py-1 text-sm">
                        <option value="zh">中文</option>
                        <option value="en">English</option>
                    </select>
                    <div class="flex items-center space-x-2">
                        <i class="fas fa-user-circle text-gray-400"></i>
                        <span class="text-sm">管理员</span>
                    </div>
                </div>
            </div>
        </div>
    </nav>

    <!-- 主要内容区 -->
    <div class="container mx-auto px-4 pt-20 pb-8">
        <div class="glass-effect rounded-xl p-6 space-y-6">
            <!-- 标题区域 -->
            <div class="flex justify-between items-center">
                <div>
                    <h2 class="text-2xl font-bold">一体化自动部署方案</h2>
                    <p class="text-gray-400 text-sm mt-1">安全、高效、一键部署</p>
                </div>
                <div class="flex space-x-4">
                    <button class="bg-blue-500 hover:bg-blue-600 px-4 py-2 rounded-lg text-sm" 
                            onclick="showHelp()">
                        <i class="fas fa-question-circle mr-2"></i>使用帮助
                    </button>
                </div>
            </div>

            <!-- 配置选项卡 -->
            <div class="border-b border-gray-700">
                <div class="flex space-x-6">
                    <button class="tab-active px-4 py-3 text-sm font-medium" data-tab="basic">
                        <i class="fas fa-cog mr-2"></i>基础配置
                    </button>
                    <button class="px-4 py-3 text-sm font-medium" data-tab="security">
                        <i class="fas fa-shield-alt mr-2"></i>安全配置
                    </button>
                    <button class="px-4 py-3 text-sm font-medium" data-tab="advanced">
                        <i class="fas fa-tools mr-2"></i>高级配置
                    </button>
                    <button class="px-4 py-3 text-sm font-medium" data-tab="monitor">
                        <i class="fas fa-chart-line mr-2"></i>监控面板
                    </button>
                </div>
            </div>

            <!-- 配置内容区 -->
            <div class="tab-content">
                <!-- 基础配置 -->
                <div id="basicConfig" class="space-y-6">
                    <!-- Git配置部分 -->
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                        <!-- 左侧 Git 配置 -->
                        <div class="space-y-4">
                            <h3 class="text-xl font-semibold mb-4">
                                <i class="fas fa-code-branch mr-2"></i>Git 配置
                            </h3>
                            <!-- Git配置表单 -->
                            <div class="space-y-4">
                                <!-- 后端仓库配置 -->
                                <div class="relative">
                                    <label class="block mb-2 text-sm">后端仓库地址</label>
                                    <div class="flex space-x-2">
                                        <input type="text" 
                                               class="input-style w-full rounded-lg px-4 py-2 text-sm" 
                                               id="backendRepo" 
                                               placeholder="请输入仓库地址，例如: https://gitee.com/username/repo.git"
                                               onchange="handleRepoChange('backend')">
                                        <button class="bg-blue-500 px-4 rounded-lg hover:bg-blue-600 tooltip"
                                                data-tooltip="配置认证"
                                                onclick="showAuthConfig('backend')">
                                            <i class="fas fa-key"></i>
                                        </button>
                                        <button class="bg-blue-500 px-4 rounded-lg hover:bg-blue-600 tooltip"
                                                data-tooltip="测试连接"
                                                onclick="testGitConnection('backend')">
                                            <i class="fas fa-link"></i>
                                        </button>
                                    </div>
                                    <div id="backendRepoStatus" class="absolute right-20 top-9 hidden">
                                        <i class="fas fa-check-circle text-green-400"></i>
                                    </div>
                                </div>

                                <!-- 前端仓库配置 -->
                                <div class="relative">
                                    <label class="block mb-2 text-sm">前端仓库地址</label>
                                    <div class="flex space-x-2">
                                        <input type="text" 
                                               class="input-style w-full rounded-lg px-4 py-2 text-sm" 
                                               id="frontendRepo" 
                                               placeholder="请输入仓库地址，例如: https://gitee.com/username/repo.git"
                                               onchange="handleRepoChange('frontend')">
                                        <button class="bg-blue-500 px-4 rounded-lg hover:bg-blue-600 tooltip"
                                                data-tooltip="配置认证"
                                                onclick="showAuthConfig('frontend')">
                                            <i class="fas fa-key"></i>
                                        </button>
                                        <button class="bg-blue-500 px-4 rounded-lg hover:bg-blue-600 tooltip"
                                                data-tooltip="测试连接"
                                                onclick="testGitConnection('frontend')">
                                            <i class="fas fa-link"></i>
                                        </button>
                                    </div>
                                    <div id="frontendRepoStatus" class="absolute right-20 top-9 hidden">
                                        <i class="fas fa-check-circle text-green-400"></i>
                                    </div>
                                </div>
                                <!-- 分支选择 -->
                                <div class="grid grid-cols-2 gap-4">
                                    <div>
                                        <label class="block mb-2 text-sm">后端分支</label>
                                        <select class="input-style w-full rounded-lg px-4 py-2 text-sm" 
                                                id="backendBranch">
                                            <option value="">请先连接仓库</option>
                                        </select>
                                    </div>
                                    <div>
                                        <label class="block mb-2 text-sm">前端分支</label>
                                        <select class="input-style w-full rounded-lg px-4 py-2 text-sm" 
                                                id="frontendBranch">
                                            <option value="">请先连接仓库</option>
                                        </select>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- 右侧部署配置 -->
                        <div class="space-y-4">
                            <h3 class="text-xl font-semibold mb-4">
                                <i class="fas fa-server mr-2"></i>部署配置
                            </h3>
                            <!-- 部署配置表单 -->
                            <div class="space-y-4">
                                <div>
                                    <label class="block mb-2 text-sm">部署环境</label>
                                    <select class="input-style w-full rounded-lg px-4 py-2 text-sm" 
                                            id="deployEnv">
                                        <option value="prod">生产环境</option>
                                        <option value="test">测试环境</option>
                                        <option value="dev">开发环境</option>
                                    </select>
                                </div>
                                <div>
                                    <label class="block mb-2 text-sm">后端部署路径</label>
                                    <input type="text" 
                                           class="input-style w-full rounded-lg px-4 py-2 text-sm" 
                                           id="backendPath" 
                                           placeholder="/path/to/backend">
                                </div>
                                <div>
                                    <label class="block mb-2 text-sm">前端部署路径</label>
                                    <input type="text" 
                                           class="input-style w-full rounded-lg px-4 py-2 text-sm" 
                                           id="frontendPath" 
                                           placeholder="/path/to/frontend">
                                </div>
                                <div>
                                    <label class="block mb-2 text-sm">部署配置</label>
                                    <div class="space-y-2">
                                        <label class="flex items-center space-x-2">
                                            <input type="checkbox" class="form-checkbox" id="autoRestart">
                                            <span class="text-sm">部署后自动重启服务</span>
                                        </label>
                                        <label class="flex items-center space-x-2">
                                            <input type="checkbox" class="form-checkbox" id="backupBefore">
                                            <span class="text-sm">部署前备份当前版本</span>
                                        </label>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

                    <!-- 进度条部分 -->
                    <div class="progress-bars space-y-4 mt-6">
                        <div class="progress-item">
                            <div class="flex justify-between mb-2">
                                <span class="text-sm">代码拉取</span>
                                <span class="text-sm" id="gitProgress">0%</span>
                            </div>
                            <div class="progress-bar bg-gray-700 rounded-full h-2 cursor-pointer tooltip" 
                                 data-tooltip="点击查看详情"
                                 onclick="showStepDetails('git')" 
                                 data-step="git">
                                <div class="progress-fill bg-blue-500 rounded-full h-2" style="width: 0%"></div>
                            </div>
                        </div>

                        <div class="progress-item">
                            <div class="flex justify-between mb-2">
                                <span class="text-sm">依赖安装</span>
                                <span class="text-sm" id="dependencyProgress">0%</span>
                            </div>
                            <div class="progress-bar bg-gray-700 rounded-full h-2 cursor-pointer tooltip"
                                 data-tooltip="点击查看详情"
                                 onclick="showStepDetails('dependency')" 
                                 data-step="dependency">
                                <div class="progress-fill bg-blue-500 rounded-full h-2" style="width: 0%"></div>
                            </div>
                        </div>

                        <div class="progress-item">
                            <div class="flex justify-between mb-2">
                                <span class="text-sm">构建打包</span>
                                <span class="text-sm" id="buildProgress">0%</span>
                            </div>
                            <div class="progress-bar bg-gray-700 rounded-full h-2 cursor-pointer tooltip"
                                 data-tooltip="点击查看详情"
                                 onclick="showStepDetails('build')" 
                                 data-step="build">
                                <div class="progress-fill bg-blue-500 rounded-full h-2" style="width: 0%"></div>
                            </div>
                        </div>

                        <div class="progress-item">
                            <div class="flex justify-between mb-2">
                                <span class="text-sm">服务部署</span>
                                <span class="text-sm" id="deployProgress">0%</span>
                            </div>
                            <div class="progress-bar bg-gray-700 rounded-full h-2 cursor-pointer tooltip"
                                 data-tooltip="点击查看详情"
                                 onclick="showStepDetails('deploy')" 
                                 data-step="deploy">
                                <div class="progress-fill bg-blue-500 rounded-full h-2" style="width: 0%"></div>
                            </div>
                        </div>
                    </div>
                                        <!-- 操作按钮 -->
                    <div class="flex justify-end space-x-4 pt-6">
                        <button class="bg-gray-600 hover:bg-gray-700 px-6 py-2 rounded-lg text-sm flex items-center" 
                                onclick="previewScript()">
                            <i class="fas fa-eye mr-2"></i>预览脚本
                        </button>
                        <button class="bg-blue-500 hover:bg-blue-600 px-6 py-2 rounded-lg text-sm flex items-center" 
                                onclick="startDeploy()">
                            <i class="fas fa-rocket mr-2"></i>开始部署
                        </button>
                    </div>
                </div>

                <!-- 其他配置标签页 -->
                <div id="securityConfig" class="hidden">
                    <div class="p-4 text-center text-gray-400">
                        <i class="fas fa-tools text-4xl mb-4"></i>
                        <p>安全配置功能开发中...</p>
                    </div>
                </div>
                <div id="advancedConfig" class="hidden">
                    <div class="p-4 text-center text-gray-400">
                        <i class="fas fa-tools text-4xl mb-4"></i>
                        <p>高级配置功能开发中...</p>
                    </div>
                </div>
                <div id="monitorConfig" class="hidden">
                    <div class="p-4 text-center text-gray-400">
                        <i class="fas fa-tools text-4xl mb-4"></i>
                        <p>监控面板功能开发中...</p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 认证配置模态框 -->
    <div id="authModal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center z-50">
        <div class="bg-gray-800 rounded-xl p-6 max-w-lg w-full mx-4">
            <div class="flex justify-between items-center mb-4">
                <h3 class="text-xl font-semibold">仓库认证配置</h3>
                <button onclick="closeAuthModal()" class="text-gray-400 hover:text-white">
                    <i class="fas fa-times"></i>
                </button>
            </div>
            
            <div class="space-y-4">
                <div>
                    <label class="block mb-2 text-sm">认证方式</label>
                    <select class="input-style w-full rounded-lg px-4 py-2 text-sm" 
                            id="authType"
                            onchange="handleAuthTypeChange()">
                        <option value="none">无需认证</option>
                        <option value="password">用户名密码</option>
                        <option value="ssh">SSH密钥</option>
                        <option value="token">访问令牌</option>
                    </select>
                </div>

                <div id="authFields" class="space-y-4 hidden">
                    <!-- 动态认证字段将在这里显示 -->
                </div>
            </div>

            <div class="flex justify-end space-x-4 mt-6">
                <button class="bg-gray-600 hover:bg-gray-700 px-4 py-2 rounded-lg text-sm"
                        onclick="closeAuthModal()">
                    取消
                </button>
                <button class="bg-blue-500 hover:bg-blue-600 px-4 py-2 rounded-lg text-sm"
                        onclick="saveAuthConfig()">
                    保存配置
                </button>
            </div>
        </div>
    </div>

    <!-- 脚本预览模态框 -->
    <div id="scriptModal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center z-50">
        <div class="bg-gray-800 rounded-xl p-6 max-w-4xl w-full mx-4">
            <div class="flex justify-between items-center mb-4">
                <h3 class="text-xl font-semibold">部署脚本预览</h3>
                <button onclick="closeScriptModal()" class="text-gray-400 hover:text-white">
                    <i class="fas fa-times"></i>
                </button>
            </div>
            <pre id="scriptContent" class="bg-gray-900 rounded-lg p-4 overflow-x-auto text-sm"></pre>
            <div class="flex justify-end mt-4">
                <button class="bg-blue-500 hover:bg-blue-600 px-4 py-2 rounded-lg text-sm"
                        onclick="copyScript()">
                    <i class="fas fa-copy mr-2"></i>复制脚本
                </button>
            </div>
        </div>
    </div>

    <!-- 部署确认模态框 -->
    <div id="confirmModal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center z-50">
        <div class="bg-gray-800 rounded-xl p-6 max-w-lg w-full mx-4">
            <h3 class="text-xl font-semibold mb-4">确认部署</h3>
            <p class="text-gray-400 mb-4">确定要开始部署吗？此操作将会：</p>
            <ul class="list-disc list-inside text-gray-400 mb-4 space-y-2">
                <li>拉取最新代码</li>
                <li>安装项目依赖</li>
                <li>构建项目</li>
                <li>重启相关服务</li>
            </ul>
            <div class="flex justify-end space-x-4">
                <button class="bg-gray-600 hover:bg-gray-700 px-4 py-2 rounded-lg text-sm"
                        onclick="closeConfirmModal()">
                    取消
                </button>
                <button class="bg-blue-500 hover:bg-blue-600 px-4 py-2 rounded-lg text-sm"
                        onclick="confirmDeploy()">
                    确认部署
                </button>
            </div>
        </div>
    </div>

    <!-- 步骤详情模态框 -->
    <div id="stepDetailsModal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center z-50">
        <div class="bg-gray-800 rounded-xl p-6 max-w-4xl w-full mx-4">
            <div class="flex justify-between items-center mb-4">
                <h3 class="text-xl font-semibold" id="stepDetailsTitle">步骤详情</h3>
                <button onclick="closeStepDetails()" class="text-gray-400 hover:text-white">
                    <i class="fas fa-times"></i>
                </button>
            </div>
            <div id="stepDetailsContent" class="bg-gray-900 rounded-lg p-4 h-96 overflow-y-auto font-mono text-sm">
                <!-- 日志内容将在这里显示 -->
            </div>
        </div>
    </div>

    <!-- 版权信息 -->
    <footer class="fixed bottom-0 left-0 right-0 bg-gray-800 bg-opacity-50 backdrop-filter backdrop-blur-sm">
        <div class="container mx-auto px-4 py-3">
            <div class="flex justify-between items-center text-sm text-gray-400">
                <div class="flex items-center space-x-2">
                    <i class="fas fa-code"></i>
                    <span>ETNOR-OPS © 2024</span>
                </div>
                <div class="flex items-center space-x-4">
                    <a href="#" class="hover:text-gray-300">
                        <i class="fab fa-github"></i>
                    </a>
                    <a href="#" class="hover:text-gray-300">
                        <i class="fab fa-gitlab"></i>
                    </a>
                    <span>|</span>
                    <span>Version 1.0.0</span>
                </div>
            </div>
        </div>
    </footer>
    
    
    
    
    <script>
// 全局状态管理
const state = {
    currentStep: 'git',
    isDeploying: false,
    steps: ['git', 'dependency', 'build', 'deploy'],
    stepProgress: {
        git: 0,
        dependency: 0,
        build: 0,
        deploy: 0
    },
    deploymentLogs: {},
    currentRepo: null
};

// 认证相关状态
const authState = {
    currentRepo: null,
    authConfigs: {
        backend: { type: 'none', config: {} },
        frontend: { type: 'none', config: {} }
    }
};

// 工具函数
const utils = {
    showToast(message, type = 'info') {
        Toastify({
            text: message,
            duration: 3000,
            gravity: "top",
            position: "right",
            backgroundColor: type === 'error' ? '#f56565' : 
                           type === 'success' ? '#48bb78' : '#4299e1',
            stopOnFocus: true
        }).showToast();
    },

    async sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    },

    generateUUID() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            const r = Math.random() * 16 | 0;
            const v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    },

    validateInputs() {
        const requiredFields = {
            backendRepo: '后端仓库地址',
            frontendRepo: '前端仓库地址',
            backendBranch: '后端分支',
            frontendBranch: '前端分支',
            backendPath: '后端部署路径',
            frontendPath: '前端部署路径'
        };

        for (const [id, name] of Object.entries(requiredFields)) {
            const value = document.getElementById(id).value.trim();
            if (!value) {
                this.showToast(`请填写${name}`, 'error');
                return false;
            }
        }
        return true;
    },

    async copyToClipboard(text) {
        try {
            await navigator.clipboard.writeText(text);
            this.showToast('复制成功', 'success');
        } catch (err) {
            this.showToast('复制失败', 'error');
        }
    },

    appendLog(step, message) {
        if (!state.deploymentLogs[step]) {
            state.deploymentLogs[step] = [];
        }
        const timestamp = new Date().toLocaleTimeString();
        state.deploymentLogs[step].push(`[${timestamp}] ${message}`);
        
        // 如果当前正在显示该步骤的详情，则更新显示
        const detailsContent = document.getElementById('stepDetailsContent');
        if (detailsContent && state.currentStep === step) {
            detailsContent.innerHTML = state.deploymentLogs[step].join('<br>');
            detailsContent.scrollTop = detailsContent.scrollHeight;
        }
    }
};

// Git相关操作
const gitOperations = {
    async fetchBranches(type) {
        const repoInput = document.getElementById(`${type}Repo`);
        const branchSelect = document.getElementById(`${type}Branch`);
        const statusIcon = document.getElementById(`${type}RepoStatus`);
        const repoUrl = repoInput.value.trim();
        
        if (!repoUrl) {
            utils.showToast('请输入仓库地址', 'error');
            return;
        }
        
        try {
            branchSelect.innerHTML = '<option value="">加载中...</option>';
            statusIcon.innerHTML = '<div class="loading-spinner"></div>';
            statusIcon.classList.remove('hidden');
            
            // 发送获取分支请求
            const response = await axios.post('/api/git/branches', {
                repoUrl,
                auth: authState.authConfigs[type]
            });
            
            if (response.data.success && Array.isArray(response.data.data)) {
            // 确保 response.data.data 是数组
            branchSelect.innerHTML = '<option value="">请选择分支</option>' + 
                response.data.data.map(branch => 
                    `<option value="${branch}">${branch}</option>`
                ).join('');
            
            statusIcon.innerHTML = '<i class="fas fa-check-circle text-green-400"></i>';
            utils.showToast(`${type}仓库分支获取成功`, 'success');
            } else {
                throw new Error(response.data.message);
            }
        } catch (error) {
            console.error('获取分支失败:', error);
            branchSelect.innerHTML = '<option value="">获取失败</option>';
            statusIcon.innerHTML = '<i class="fas fa-times-circle text-red-400"></i>';
            utils.showToast(error.message || `${type}仓库分支获取失败`, 'error');
        }
    },

    async testConnection(type) {
        const statusIcon = document.getElementById(`${type}RepoStatus`);
        const repoUrl = document.getElementById(`${type}Repo`).value.trim();
        
        if (!repoUrl) {
            utils.showToast('请输入仓库地址', 'error');
            return;
        }
        
        try {
            statusIcon.innerHTML = '<div class="loading-spinner"></div>';
            statusIcon.classList.remove('hidden');
            
            const response = await axios.post('/api/git/test-connection', {
                repoUrl,
                auth: authState.authConfigs[type]
            });
            
            if (response.data.success) {
                statusIcon.innerHTML = '<i class="fas fa-check-circle text-green-400"></i>';
                utils.showToast(`${type}仓库连接测试成功`, 'success');
                await this.fetchBranches(type);
            } else {
                throw new Error(response.data.message);
            }
        } catch (error) {
            statusIcon.innerHTML = '<i class="fas fa-times-circle text-red-400"></i>';
            utils.showToast(error.message || `${type}仓库连接测试失败`, 'error');
        }
    }
};


// 部署管理
const deploymentManager = {
    updateProgress(step, progress) {
        state.stepProgress[step] = progress;
        document.getElementById(`${step}Progress`).textContent = `${progress}%`;
        document.querySelector(`[data-step="${step}"] .progress-fill`).style.width = `${progress}%`;
        utils.appendLog(step, `进度更新: ${progress}%`);
    },

    async deploy() {
        console.log('deploymentManager.deploy() 开始执行'); // 添加日志
        
        
        if (!utils.validateInputs()) return;
        
        state.isDeploying = true;
        const deployId = Date.now().toString();
        console.log('准备构建部署配置'); // 添加日志
        const deployConfig = {
            backend: {
                repo: document.getElementById('backendRepo').value,
                branch: document.getElementById('backendBranch').value,
                path: document.getElementById('backendPath').value,
                auth: {
                    type: authState.authConfigs.backend.type.toUpperCase(),
                    username: authState.authConfigs.backend.config?.username,
                    password: authState.authConfigs.backend.config?.password,
                    token: authState.authConfigs.backend.config?.token,
                    sshKey: authState.authConfigs.backend.config?.sshKey,
                    passphrase: authState.authConfigs.backend.config?.passphrase
                }
            },
            frontend: {
                repo: document.getElementById('frontendRepo').value,
                branch: document.getElementById('frontendBranch').value,
                path: document.getElementById('frontendPath').value,
                auth: {
                    type: authState.authConfigs.frontend.type.toUpperCase(),
                    username: authState.authConfigs.frontend.config?.username,
                    password: authState.authConfigs.frontend.config?.password,
                    token: authState.authConfigs.frontend.config?.token,
                    sshKey: authState.authConfigs.frontend.config?.sshKey,
                    passphrase: authState.authConfigs.frontend.config?.passphrase
                }
            },
            env: document.getElementById('deployEnv').value,
            options: {
                autoRestart: document.getElementById('autoRestart').checked,
                backupBefore: document.getElementById('backupBefore').checked
            }
        };
        console.log('部署配置:', deployConfig); // 添加日志

        try {
            // 清空之前的日志
            state.deploymentLogs = {};
            console.log('准备发送部署请求'); // 添加日志
             // 发送部署请求
             const response = await axios.post('/api/deploy/start', deployConfig);
            console.log('部署请求响应:', response); // 添加日志
            
            // 开始部署流程
            for (const step of state.steps) {
                if (!state.isDeploying) break;
                
                state.currentStep = step;
                utils.appendLog(step, `开始${this.getStepName(step)}...`);
                
                try {
                    await this.executeStep(step, deployConfig);
                } catch (error) {
                    utils.appendLog(step, `错误: ${error.message}`);
                    throw error;
                }
            }
            
            if (state.isDeploying) {
                utils.showToast('部署完成！', 'success');
                utils.appendLog('deploy', '部署完成！');
            }
        } catch (error) {
            utils.showToast(error.message || '部署失败', 'error');
        } finally {
            state.isDeploying = false;
        }
    },

    async executeStep(step, config) {
        const endpoint = `/api/deploy/${step}`;
        const socket = new WebSocket(`ws://${window.location.host}/ws/deploy/${config.deployId}`);
        
        return new Promise((resolve, reject) => {
            socket.onmessage = (event) => {
                const data = JSON.parse(event.data);
                if (data.type === 'progress') {
                    this.updateProgress(step, data.progress);
                } else if (data.type === 'log') {
                    utils.appendLog(step, data.message);
                }
            };

            socket.onerror = (error) => {
                reject(new Error('WebSocket连接失败'));
            };

            socket.onclose = () => {
                if (state.stepProgress[step] === 100) {
                    resolve();
                } else {
                    reject(new Error(`${this.getStepName(step)}失败`));
                }
            };
        });
    },

    getStepName(step) {
        const stepNames = {
            git: '代码拉取',
            dependency: '依赖安装',
            build: '构建打包',
            deploy: '服务部署'
        };
        return stepNames[step] || step;
    },

    stopDeployment() {
        state.isDeploying = false;
        utils.showToast('部署已停止', 'info');
        utils.appendLog(state.currentStep, '部署已手动停止');
    }
};

// UI交互处理
const uiHandler = {
    showAuthModal(repoType) {
        authState.currentRepo = repoType;
        const currentConfig = authState.authConfigs[repoType];
        
        document.getElementById('authType').value = currentConfig.type;
        document.getElementById('authModal').classList.remove('hidden');
        this.handleAuthTypeChange();
    },

    closeAuthModal() {
        document.getElementById('authModal').classList.add('hidden');
    },

    handleAuthTypeChange() {
        const authType = document.getElementById('authType').value;
        const authFields = document.getElementById('authFields');
        
        authFields.innerHTML = '';
        
        switch(authType) {
            case 'none':
                authFields.classList.add('hidden');
                break;
                
            case 'password':
                authFields.classList.remove('hidden');
                authFields.innerHTML = `
                    <div>
                        <label class="block mb-2 text-sm">用户名</label>
                        <input type="text" class="input-style w-full rounded-lg px-4 py-2 text-sm" id="username">
                    </div>
                    <div>
                        <label class="block mb-2 text-sm">密码</label>
                        <input type="password" class="input-style w-full rounded-lg px-4 py-2 text-sm" id="password">
                    </div>
                `;
                break;
                
            case 'ssh':
                authFields.classList.remove('hidden');
                authFields.innerHTML = `
                    <div>
                        <label class="block mb-2 text-sm">SSH私钥路径</label>
                        <input type="text" class="input-style w-full rounded-lg px-4 py-2 text-sm" id="sshKey">
                    </div>
                    <div>
                        <label class="block mb-2 text-sm">密码短语（可选）</label>
                        <input type="password" class="input-style w-full rounded-lg px-4 py-2 text-sm" id="passphrase">
                    </div>
                `;
                break;
                
            case 'token':
                authFields.classList.remove('hidden');
                authFields.innerHTML = `
                    <div>
                        <label class="block mb-2 text-sm">访问令牌</label>
                        <input type="password" class="input-style w-full rounded-lg px-4 py-2 text-sm" id="token">
                    </div>
                `;
                break;
        }
    },

    saveAuthConfig() {
        const authType = document.getElementById('authType').value;
        const config = {};
        
        switch(authType) {
            case 'password':
                config.username = document.getElementById('username').value;
                config.password = document.getElementById('password').value;
                break;
            case 'ssh':
                config.sshKey = document.getElementById('sshKey').value;
                config.passphrase = document.getElementById('passphrase').value;
                break;
            case 'token':
                config.token = document.getElementById('token').value;
                break;
        }
        
        authState.authConfigs[authState.currentRepo] = {
            type: authType,
            config: config
        };
        
        utils.showToast('认证配置已保存', 'success');
        this.closeAuthModal();
    },

    showScriptModal() {
        document.getElementById('scriptModal').classList.remove('hidden');
        this.generateDeployScript();
    },

    closeScriptModal() {
        document.getElementById('scriptModal').classList.add('hidden');
    },

    showConfirmModal() {
        document.getElementById('confirmModal').classList.remove('hidden');
    },

    closeConfirmModal() {
        document.getElementById('confirmModal').classList.add('hidden');
    },

    showStepDetails(step) {
        const modal = document.getElementById('stepDetailsModal');
        const title = document.getElementById('stepDetailsTitle');
        const content = document.getElementById('stepDetailsContent');
        
        title.textContent = `${deploymentManager.getStepName(step)}详情`;
        content.innerHTML = (state.deploymentLogs[step] || []).join('<br>');
        
        modal.classList.remove('hidden');
        content.scrollTop = content.scrollHeight;
    },

    closeStepDetails() {
        document.getElementById('stepDetailsModal').classList.add('hidden');
    },

    generateDeployScript() {
        const config = {
            backend: {
                repo: document.getElementById('backendRepo').value,
                branch: document.getElementById('backendBranch').value,
                path: document.getElementById('backendPath').value
            },
            frontend: {
                repo: document.getElementById('frontendRepo').value,
                branch: document.getElementById('frontendBranch').value,
                path: document.getElementById('frontendPath').value
            },
            env: document.getElementById('deployEnv').value,
            autoRestart: document.getElementById('autoRestart').checked,
            backupBefore: document.getElementById('backupBefore').checked
        };

        const script = `#!/bin/bash

# 部署配置
BACKEND_REPO="${config.backend.repo}"
BACKEND_BRANCH="${config.backend.branch}"
BACKEND_PATH="${config.backend.path}"
FRONTEND_REPO="${config.frontend.repo}"
FRONTEND_BRANCH="${config.frontend.branch}"
FRONTEND_PATH="${config.frontend.path}"
DEPLOY_ENV="${config.env}"
AUTO_RESTART=${config.autoRestart}
BACKUP_BEFORE=${config.backupBefore}

# 部署脚本内容
echo "开始部署..."
# ... 生成实际的部署脚本内容 ...
`;

        document.getElementById('scriptContent').textContent = script;
    }
};



function handleRepoChange(type) {
    const statusIcon = document.getElementById(`${type}RepoStatus`);
    statusIcon.classList.add('hidden');
    document.getElementById(`${type}Branch`).innerHTML = '<option value="">请先连接仓库</option>';
}

function testGitConnection(type) {
    gitOperations.testConnection(type);
}

function showAuthConfig(type) {
    uiHandler.showAuthModal(type);
}

function closeAuthModal() {
    uiHandler.closeAuthModal();
}

function handleAuthTypeChange() {
    uiHandler.handleAuthTypeChange();
}

function saveAuthConfig() {
    uiHandler.saveAuthConfig();
}

function showStepDetails(step) {
    uiHandler.showStepDetails(step);
}

function closeStepDetails() {
    uiHandler.closeStepDetails();
}

function previewScript() {
    uiHandler.showScriptModal();
}

function closeScriptModal() {
    uiHandler.closeScriptModal();
}

function copyScript() {
    const scriptContent = document.getElementById('scriptContent').textContent;
    utils.copyToClipboard(scriptContent);
}

function startDeploy() {
    console.log('开始部署流程...'); // 添加日志
    uiHandler.showConfirmModal();
}

function closeConfirmModal() {
    uiHandler.closeConfirmModal();
}

async function confirmDeploy() {
    console.log('confirmDeploy 函数被调用');  // 添加日志
    
    uiHandler.closeConfirmModal();
    
    try {
        console.log('准备调用 deploymentManager.deploy()');  // 添加日志
        if (!deploymentManager || typeof deploymentManager.deploy !== 'function') {
            console.error('deploymentManager 对象或 deploy 方法未定义:', deploymentManager);  // 检查对象
            return;
        }
        
        await deploymentManager.deploy();
        console.log('deploy 执行完成');  // 添加日志
    } catch (error) {
        console.error('部署过程出错:', error);
        utils.showToast('部署失败: ' + error.message, 'error');
    }
}

function showHelp() {
    utils.showToast('帮助文档正在完善中...', 'info');
}

// WebSocket 连接管理
const wsManager = {
    socket: null,
    
    connect(deployId) {
        this.disconnect();
        this.socket = new WebSocket(`ws://${window.location.host}/ws/deploy/${deployId}`);
        
        this.socket.onopen = () => {
            utils.appendLog('system', 'WebSocket连接已建立');
        };
        
        this.socket.onmessage = (event) => {
            const data = JSON.parse(event.data);
            if (data.type === 'progress') {
                deploymentManager.updateProgress(data.step, data.progress);
            } else if (data.type === 'log') {
                utils.appendLog(data.step, data.message);
            }
        };
        
        this.socket.onclose = () => {
            utils.appendLog('system', 'WebSocket连接已关闭');
        };
        
        this.socket.onerror = (error) => {
            utils.appendLog('system', 'WebSocket连接错误');
            utils.showToast('部署连接出错', 'error');
        };
    },
    
    disconnect() {
        if (this.socket) {
            this.socket.close();
            this.socket = null;
        }
    },
    
    send(message) {
        if (this.socket && this.socket.readyState === WebSocket.OPEN) {
            this.socket.send(JSON.stringify(message));
        }
    }
};

// 错误处理
window.onerror = function(message, source, lineno, colno, error) {
    console.error('Global error:', error);
    utils.showToast('系统错误，请查看控制台', 'error');
};

// API 请求拦截器
axios.interceptors.response.use(
    response => response,
    error => {
        const message = error.response?.data?.message || error.message || '请求失败';
        utils.showToast(message, 'error');
        return Promise.reject(error);
    }
);

// 页面加载完成后的初始化
document.addEventListener('DOMContentLoaded', () => {
    // 初始化标签页切换事件
    document.querySelectorAll('[data-tab]').forEach(tab => {
        tab.addEventListener('click', (e) => {
            const tabName = e.currentTarget.dataset.tab;
            
            // 更新标签页样式
            document.querySelectorAll('[data-tab]').forEach(t => {
                t.classList.remove('tab-active');
            });
            e.currentTarget.classList.add('tab-active');
            
            // 切换内容区域
            document.querySelectorAll('.tab-content > div').forEach(panel => {
                panel.classList.add('hidden');
            });
            document.getElementById(`${tabName}Config`).classList.remove('hidden');
        });
    });
    
    // 初始化语言切换
    document.getElementById('language').addEventListener('change', (e) => {
        const lang = e.target.value;
        utils.showToast('语言切换功能开发中...', 'info');
    });
    
    // 初始化部署路径默认值
    const defaultPaths = {
        dev: {
            backend: '/var/www/dev/backend',
            frontend: '/var/www/dev/frontend'
        },
        test: {
            backend: '/var/www/test/backend',
            frontend: '/var/www/test/frontend'
        },
        prod: {
            backend: '/var/www/prod/backend',
            frontend: '/var/www/prod/frontend'
        }
    };
    
    document.getElementById('deployEnv').addEventListener('change', (e) => {
        const env = e.target.value;
        document.getElementById('backendPath').value = defaultPaths[env].backend;
        document.getElementById('frontendPath').value = defaultPaths[env].frontend;
    });
    
    // 设置初始部署路径
    const initialEnv = document.getElementById('deployEnv').value;
    document.getElementById('backendPath').value = defaultPaths[initialEnv].backend;
    document.getElementById('frontendPath').value = defaultPaths[initialEnv].frontend;
    
    // 初始化模态框关闭事件
    document.querySelectorAll('.modal').forEach(modal => {
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                modal.classList.add('hidden');
            }
        });
    });
    
    // 初始化键盘事件
    document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape') {
            document.querySelectorAll('.modal').forEach(modal => {
                modal.classList.add('hidden');
            });
        }
    });
});
</script>
</body>
</html>






